/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package algorithm.bestFirstSearch_4Q;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;

class Nodecb {
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(board);
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Nodecb other = (Nodecb) obj;
		if (!Arrays.equals(board, other.board))
			return false;
		return true;
	}

	public int actualCost;// conflict
	public int heuristic; // depth
	public boolean[][] board;

	/**
	 * calculating the conflict value of the queen on the chess board. when you
	 * modify the value of board, you should invoke this function manually.
	 */
	public void initActualCost() {
		actualCost = 0;
		actualCost += check("row");
		actualCost += check("col");
		actualCost += check(Diagonal.generateDiagonal(board.length), "diagonal");
		actualCost += check(Clinodiagonal.generateDiagonal(board.length), "clinodiagonal");
	}

	private int check(ArrayList<ArrayList<Point>> lists, String arg) {
		int confliect = 0;
		int count1, count2;
		for (ArrayList<Point> list : lists) {
			count1 = count2 = 0;
			for (Point p : list) {
				if (board[p.y][p.x] == true) {// include diagonal
					count1++;
				}
				// symmetrical points
				if (arg.equals("diagonal") && (p.y != p.x) && (board[p.x][p.y] == true)) {// exclude diagonal
					count2++;
				}

				// symmetrical points
				if (arg.equals("clinodiagonal") && ((p.x + p.y) != (board.length - 1)) && (board[board.length - 1 - p.y][board.length - 1 - p.x] == true)) {// exclude clinodiagonal
					count2++;
				}
			}
			if (count1 > 1) {
				confliect++;
			}
			if (count2 > 1) {
				confliect++;
			}
		}
		return confliect;
	}

	private int check(String arg) {
		int confliect = 0;
		int count, i, j;
		for (i = 0; i < board.length; i++) {
			for (j = 0, count = 0; j < board[i].length; j++) {
				if (arg.equals("row") && board[i][j] == true) {
					count++;
				} else if (arg.equals("col") && board[j][i] == true) {
					count++;
				}
			}
			if (count > 1) {
				confliect++;
			}
		}
		return confliect;
	}

	public Nodecb() {
		this(0, 0);
	}

	public Nodecb(Nodecb node) {
		this.actualCost = node.actualCost;
		this.heuristic = node.heuristic;

		this.board = new boolean[node.board.length][];
		for (int i = 0; i < node.board.length; i++) {
			this.board[i] = new boolean[node.board[i].length];
			for (int j = 0; j < node.board[i].length; j++) {
				this.board[i][j] = node.board[i][j];
			}
		}
	}

	/**
	 * @param n
	 *            : n by n chess board
	 * @param heuristic
	 *            : search depth
	 */
	public Nodecb(int n, int heuristic) {
		this.heuristic = heuristic;
		this.actualCost = 0;
		board = new boolean[n][];
		for (int i = 0; i < board.length; i++) {
			board[i] = new boolean[n];
			for (int j = 0; j < board[i].length; j++) {
				board[i][j] = false;
			}
		}
	}

	public void disp() {
		for (boolean bb[] : board) {
			for (boolean b : bb) {
				if (b == false) {
					System.out.print("0 ");
				} else {
					System.out.print("1 ");
				}
			}
			System.out.println("");
		}
	}
}
